package com.xyy.saas.payment.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xyy.saas.payment.constants.Constants;
import com.xyy.saas.payment.cores.api.PaymentMerchantApi;
import com.xyy.saas.payment.cores.param.RegisterOrderParam;
import com.xyy.saas.payment.cores.param.WithdrawAccountParam;
import com.xyy.saas.payment.dao.mapper.SeparateOrderMapper;
import com.xyy.saas.payment.dao.model.SeparateOrder;
import com.xyy.saas.payment.dto.SeparateOrderSearchParam;
import com.xyy.saas.payment.manage.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.pojo.param.AccountTransferParam;
import com.xyy.saas.payment.pojo.param.AccountTransferVO;
import com.xyy.saas.payment.pojo.param.PairVO;
import com.xyy.saas.payment.pojo.param.QueryAccountBalanceParam;
import com.xyy.saas.payment.service.PlatformAccountsManage;
import com.xyy.saas.payment.service.auth.AuthService;
import com.xyy.saas.payment.pojo.bo.QueryAccountBo;
import com.xyy.saas.payment.exception.PaymentException;
import com.xyy.saas.payment.manage.cores.vo.ResultVO;
import com.xyy.saas.payment.util.ApolloUtil;
import com.xyy.saas.payment.util.LeafUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 管理平台账户接口
 * @date 2020/5/18 11:01
 */
@RestController
@RequestMapping("/account")
public class AccountController {

    private static Logger LOGGER = LoggerFactory.getLogger(AccountController.class);

    @Autowired
    private AuthService authService;
    @Resource
    private LeafUtil leafUtil;
    @Reference(version = "1.0.0")
    private PaymentMerchantApi paymentMerchantApi;
    @Resource
    private SeparateOrderMapper separateOrderMapper;
    @Resource
    private PlatformAccountsManage platformAccountsManage;

    /** 账户-查询账户信息 */
    @PostMapping(value = "/query",produces = "application/json;charset=utf-8")
    public ResultVO<QueryAccountBo> queryAccount(HttpServletRequest requestMsg) {
        try {
            Cookie[] cookies = requestMsg.getCookies();
            String tgc = "";
            for (Cookie c : cookies) {
                if (c.getName().equalsIgnoreCase("TGC")) {
                    tgc = c.getValue();
                    break;
                }
            }
            if (StringUtils.isEmpty(tgc)) {
                return ResultVO.createParamError("^_^您的账号没有权限");
            }
            String account = authService.checkWhiteList(tgc);
            QueryAccountBo queryAccountBo = new QueryAccountBo();
            queryAccountBo.setAccount(account);
            authService.getDataAndMenu(queryAccountBo,"login");
            return ResultVO.createSuccess(queryAccountBo);
        } catch (PaymentException e) {
            LOGGER.error("AccountController#queryAccount query error cookies:{}", JSON.toJSONString(requestMsg.getCookies()),e);
            ResultVO resultVo = ResultVO.createError("^_^您的账号没有权限");
            if ("9011".equals(e.getErrCode())){
                resultVo.setCode("9011");
            }
            return resultVo;
        }
    }

    @GetMapping(value = "/accountList")
    public ResultVO<List<PairVO>> accountList() {
        List<PairVO> accounts = new ArrayList<>();
        accounts.add(PairVO.builder().key("平台挂帐子账户").value(ApolloUtil.getProperty("ec_pingan_summary_account_id")).accountType("FUNCTION_ACCOUNT").build());
        accounts.add(PairVO.builder().key("平台退款垫资户").value(ApolloUtil.getProperty("ec_pingan_refund_account_id")).accountType("FUND_ACCOUNT").build());
        accounts.add(PairVO.builder().key("平台购物金户").value(ApolloUtil.getProperty("ec_pingan_balance_account_id")).accountType("FUND_ACCOUNT").build());
        accounts.add(PairVO.builder().key("平台营销补贴户").value(ApolloUtil.getProperty("ec_pingan_market_account_id")).accountType("FUND_ACCOUNT").build());
        accounts.add(PairVO.builder().key("平台退佣金户").value(ApolloUtil.getProperty("ec_pingan_out_brokerage_account_id")).accountType("FUND_ACCOUNT").build());
        accounts.add(PairVO.builder().key("平台收佣金户（含退回补贴/购物金）").value(ApolloUtil.getProperty("ec_pingan_in_brokerage_account_id")).accountType("FUNCTION_ACCOUNT").build());
        accounts.add(PairVO.builder().key("平台提现专用户").value(ApolloUtil.getProperty("ec_pingan_platform_aggr_withdraw_account_id")).accountType("FUND_ACCOUNT").build());
        return ResultVO.createSuccess(accounts);
    }

    @PostMapping(value = "/accountTransfer")
    public ResultVO<Boolean> accountTransfer(@RequestBody AccountTransferParam param) {
        LOGGER.info("AccountController#accountTransfer param={}", JSONObject.toJSONString(param));

        try {
            param.checkParam();
            String summaryAccountId = ApolloUtil.getProperty("ec_pingan_summary_account_id");
            com.xyy.saas.payment.cores.vo.ResultVO<Boolean> resultVO = null;
            String businessOrderNo = "manage_account_transfer_" + leafUtil.getSnowflakeId();

            if (isSpecificAccountPingAnWithdraw(param)) {
                WithdrawAccountParam withdrawAccountParam = new WithdrawAccountParam()
                        .setPayerName(Constants.specificPayerName)
                        .setPayerAccountNo(Constants.specificPayerAccountNo)
                        .setPayeeName(Constants.specificPayeeName)
                        .setPayeeAccountNo(Constants.specificPayeeAccountNo)
                        .setUserId(Constants.specificUserId)
                        .setAmount(param.getAmount());
                paymentMerchantApi.withdraw2(withdrawAccountParam);
                return ResultVO.createSuccess(Boolean.TRUE);
            }

            // 出账方是挂账子账户，走挂账
            if(Objects.equals(summaryAccountId, param.getOutAccountId())) {
                resultVO = paymentMerchantApi.registerOrder(RegisterOrderParam.builder().
                        businessIdType(param.getBusinessIdType()).
                        accountId(param.getInAccountId()).
                        businessOrderNo(businessOrderNo).
                        amount(param.getAmount()).
                        remark(param.getRemark()).
                        build());
            }
            // 走转账
            else {
                resultVO = paymentMerchantApi.accountTransfer(com.xyy.saas.payment.cores.param.AccountTransferParam.builder().
                        transferType(com.xyy.saas.payment.cores.param.AccountTransferParam.TRANSFER_PAY).
                        businessIdType(param.getBusinessIdType()).
                        outAccountId(param.getOutAccountId()).
                        inAccountId(param.getInAccountId()).
                        amount(param.getAmount()).
                        businessOrderNo(businessOrderNo).
                        remark(param.getRemark()).
                        build());
            }

            if(resultVO.isSuccess()) {
                return ResultVO.createSuccess(resultVO.getResult());
            }
            else {
                return ResultVO.createError(resultVO.getCode(), resultVO.getMsg(), resultVO.getResult());
            }
        }
        catch(Exception ex) {
            LOGGER.info("AccountController#accountTransfer param=" + JSONObject.toJSONString(param), ex);

            if(ex instanceof PaymentException) {
                return ResultVO.createError(((PaymentException) ex).getErrCode(), ((PaymentException) ex).getErrMsg(), Boolean.FALSE);
            }
            else {
                return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR, Boolean.FALSE);
            }
        }
    }

    private boolean isSpecificAccountPingAnWithdraw(AccountTransferParam param) {
        return param != null && Objects.equals(param.getInAccountId(), Constants.specificInAccountId)
                && Objects.equals(param.getOutAccountId(), Constants.specificOutAccountId);
    }

    @PostMapping(value = "/accountTransferList")
    public ResultVO<List<AccountTransferVO>> accountTransferList(@RequestBody AccountTransferParam param) {
        LOGGER.info("AccountController#accountTransferList param={}", JSONObject.toJSONString(param));
        SeparateOrderSearchParam separateOrderSearchParam = new SeparateOrderSearchParam();
        separateOrderSearchParam.setCustMerchant(param.getOutAccountId());
        separateOrderSearchParam.setCustNoIn(param.getInAccountId());
        separateOrderSearchParam.setStatus(param.getStatus());
        separateOrderSearchParam.setStartTime(param.getStartTime());
        separateOrderSearchParam.setEndTime(param.getEndTime());
        separateOrderSearchParam.setBusinessOrderNo("manage_account_transfer_");
        List<SeparateOrder> items = separateOrderMapper.queryAll0(separateOrderSearchParam);
        List<AccountTransferVO> result = new ArrayList<>();

        if(!CollectionUtils.isEmpty(items)) {
            for(SeparateOrder item : items) {
                result.add(AccountTransferVO.transfer(item));
            }
        }

        return ResultVO.createSuccess(result);
    }

    @PostMapping(value = "/queryAccountBalance")
    public ResultVO<String> queryAccountBalance(@RequestBody QueryAccountBalanceParam param) {
        LOGGER.info("AccountController#queryAccountBalance param={}", JSONObject.toJSONString(param));
        String balance = platformAccountsManage.queryAccountBalance(param.getAccountId(), param.getAccountType());
        return ResultVO.createSuccess(balance);
    }
}
